home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 1 Issue 2 / PDCD-1 - Issue 02.iso / _utilities / utilities / 001 / fue / c / riscos < prev    next >
Text File  |  1991-06-24  |  20KB  |  816 lines

  1.  
  2. /*
  3.  * This defines Archimedes screen-handling and spawning fns - div
  4.  * (based on vt52.c & msdos files, so not necessarily the way i
  5.     would have done it - might redo it when i understand it !)
  6.  */
  7.  
  8. #define termdef 1                       /* don't define "term" external */
  9.  
  10. /*{{{  include files*/
  11. #include        <stdio.h>
  12. #include        <kernel.h>
  13. #include        <time.h>
  14. #include        "estruct.h"
  15. #include        "etype.h"
  16. #include        "edef.h"
  17. #include        "elang.h"
  18. /*}}}*/
  19.  
  20. /*{{{  part one - terminal control stuff*/
  21.  
  22. #if     RISCOS
  23.  
  24. /*{{{  various #defines*/
  25. #define NROW    31                      /* Screen size.                 */
  26. #define NCOL    80                      /* Edit if you want to.         */
  27. #define MARGIN  8                       /* size of minimim margin and   */
  28. #define SCRSIZ  64                      /* scroll size for extended lines */
  29. #define NPAUSE  500                     /* # times thru update to pause */
  30. #define ESC     0x1B                    /* ESC character.               */
  31. #define BEL     0x07                    /* ascii bell character         */
  32. /*}}}*/
  33. /*{{{  function prototypes*/
  34. extern  int     ttopen();               /* Forward references.          */
  35. extern  int     ttgetc();
  36. extern  int     ttputc();
  37. extern  int     ttflush();
  38. extern  int     ttclose();
  39. extern  int     armmove();
  40. extern  int     armeeol();
  41. extern  int     armeeop();
  42. extern  int     armbeep();
  43. extern  int     armopen();
  44. extern  int     armrev();
  45. extern  int     armcres();
  46. extern  int     armkopen();
  47. extern  int     armkclose();
  48.  
  49. #if     COLOR
  50. extern  int     armfcol();
  51. extern  int     armbcol();
  52. #endif
  53. /*}}}*/
  54.  
  55. /*{{{  despatch table*/
  56. /*
  57.  * Dispatch table. All the
  58.  * hard fields just point into the
  59.  * terminal I/O code.
  60.  */
  61. TERM    term    = {
  62.         NROW-1,
  63.         NROW-1,
  64.         NCOL,
  65.         NCOL,
  66.         MARGIN,
  67.         SCRSIZ,
  68.         NPAUSE,
  69.         armopen,
  70.         ttclose,
  71.         armkopen,
  72.         armkclose,
  73.         ttgetc,
  74.         ttputc,
  75.         ttflush,
  76.         armmove,
  77.         armeeol,
  78.         armeeop,
  79.         armbeep,
  80.         armrev,
  81.         armcres
  82. #if     COLOR
  83.       , armfcol,
  84.         armbcol
  85. #endif
  86. };
  87. /*}}}*/
  88.  
  89. /*{{{  the functions*/
  90.  
  91. /*{{{  armmove(row, col)*/
  92. armmove(row, col)
  93. {
  94.          _kernel_oswrch(31);
  95.          _kernel_oswrch(col);
  96.          _kernel_oswrch(row);
  97. }
  98. /*}}}*/
  99. /*{{{  armeeol()*/
  100. armeeol()
  101. {
  102.      _kernel_oswrch(23); _kernel_oswrch(8); /* vdu 23,8.. clears block */
  103.      _kernel_oswrch(5);  _kernel_oswrch(6); /* 5,6 = current posn->eol */
  104.      _kernel_oswrch(0);  _kernel_oswrch(0); /* lots of zeroes means no */
  105.      _kernel_oswrch(0);  _kernel_oswrch(0); /* offsets involved        */
  106.      _kernel_oswrch(0);  _kernel_oswrch(0);
  107. }
  108. /*}}}*/
  109. /*{{{  armeeop()*/
  110. armeeop()
  111. {
  112. #if COLOR
  113.   armbcol(gbcolor);  /* seem to need this - dunno why ! */
  114. #endif
  115.  
  116.      _kernel_oswrch(23); _kernel_oswrch(8); /* vdu 23,8 clears a block */
  117.      _kernel_oswrch(5);  _kernel_oswrch(10); /* from curent posn to eop */
  118.      _kernel_oswrch(0);  _kernel_oswrch(0);  /* start at current posn */
  119.      _kernel_oswrch(0);  _kernel_oswrch(0);
  120.      _kernel_oswrch(0);  _kernel_oswrch(0);
  121.   
  122. }
  123. /*}}}*/
  124. /*{{{  armrev(status)*/
  125. armrev(status) /* set the reverse video state */
  126.  
  127. int status;     /* TRUE = reverse video, FALSE = normal video */
  128.  
  129. { static int rev_vid=FALSE;
  130.   if (status != rev_vid)
  131.   {  _kernel_oswrch(23);     _kernel_oswrch(17);
  132.      _kernel_oswrch(5);      _kernel_oswrch(0);
  133.      _kernel_oswrch(0);      _kernel_oswrch(0);
  134.      _kernel_oswrch(0);      _kernel_oswrch(0);
  135.      _kernel_oswrch(0);      _kernel_oswrch(0);
  136.      rev_vid=status;
  137.   }
  138. }
  139. /*}}}*/
  140. /*{{{  armcres()*/
  141. armcres(res)
  142. char *res;
  143. {  int i=0;
  144.    printf("[cres %s]", res);
  145.    if ( (strcmp(res, "0")) && ( (i=asc_int(res))==0))
  146.         return(FALSE);
  147.  
  148.    scinit(i);     
  149.    return(TRUE);     
  150.  
  151. }
  152. /*}}}*/
  153. /*{{{  spal()*/
  154. spal()          /* change palette string */
  155.  
  156. {
  157.         /*      Does nothing here       */
  158. }
  159. /*}}}*/
  160.  
  161. #if     COLOR
  162.   /*{{{  armfcol()*/
  163.   armfcol(colour)      /* set the forground color */
  164.   int colour;
  165.   {
  166.     _kernel_oswrch(17); _kernel_oswrch(colour);
  167.   }
  168.   /*}}}*/
  169.   /*{{{  armbcol()*/
  170.   armbcol(colour)      /* set the background color */
  171.   int colour;
  172.   {
  173.     _kernel_oswrch(17); _kernel_oswrch(colour | 128);
  174.   }
  175.   /*}}}*/
  176. #endif
  177.  
  178. /*{{{  armbeep()*/
  179. armbeep()
  180. {
  181. #ifdef  BEL
  182.         ttputc(BEL);
  183.         ttflush();
  184. #endif
  185. }
  186. /*}}}*/
  187. /*{{{  armopen()*/
  188. armopen()
  189. {
  190.         scinit(-1);
  191.         ttopen();
  192. }
  193. /*}}}*/
  194. /*{{{  armkopen()*/
  195. armkopen()
  196.  
  197. {
  198. }
  199. /*}}}*/
  200. /*{{{  armkclose()*/
  201. armkclose()
  202.  
  203. {
  204. }
  205. /*}}}*/
  206.  
  207. #if     FLABEL
  208. /*{{{  fnclabel(f, n)*/
  209. fnclabel(f, n)          /* label a function key */
  210.  
  211. int f,n;        /* default flag, numeric argument [unused] */
  212.  
  213. {
  214.         /* on machines with no function keys...don't bother */
  215.         return(TRUE);
  216. }
  217. /*}}}*/
  218. #endif
  219.  
  220. /*}}}*/
  221.  
  222. #else
  223.  
  224. /*{{{  armhello()*/
  225. armhello()
  226.  
  227. {
  228. }
  229. /*}}}*/
  230.  
  231. #endif
  232. /*}}}*/
  233.  
  234. /*{{{  part two - lowlevel stuff (fn spawning, etc)*/
  235.  
  236. /*
  237.  *  This bit is based on msdos.c
  238.  *  I may tidy up when i get round to understanding how it all works
  239.  */
  240.  
  241.  
  242. /*{{{  Mouse stuff*/
  243. /* The Mouse driver only works with typeahead defined */
  244. #if     MOUSE
  245. #undef  TYPEAH
  246. #define TYPEAH  1
  247. #endif
  248. /*}}}*/
  249.  
  250. /*      Some global variable    */
  251. #define INBUFSIZ        40
  252. static int mexist;      /* is the mouse driver installed? */
  253. static int nbuttons;    /* number of buttons on the mouse */
  254. static int oldbut;      /* Previous state of mouse buttons */
  255.  
  256. /*      input buffers and pointers      */
  257.  
  258. #define IBUFSIZE        64      /* this must be a power of 2 */
  259.  
  260. unsigned char in_buf[IBUFSIZE]; /* input character buffer */
  261. int in_next = 0;                /* pos to retrieve next input character */
  262. int in_last = 0;                /* pos to place most recent input character */
  263.  
  264. /*{{{  in_init()*/
  265. in_init()       /* initialize the input buffer */
  266.  
  267. {
  268.         in_next = in_last = 0;
  269. }
  270. /*}}}*/
  271. /*{{{  in_check()*/
  272. in_check()      /* is the input buffer non-empty? */
  273.  
  274. {
  275.         if (in_next == in_last)
  276.                 return(FALSE);
  277.         else
  278.                 return(TRUE);
  279. }
  280. /*}}}*/
  281. /*{{{  in_put(event)*/
  282. in_put(event)
  283.  
  284. int event;      /* event to enter into the input buffer */
  285.  
  286. {
  287.         in_buf[in_last++] = event;
  288.         in_last &= (IBUFSIZE - 1);
  289. }
  290. /*}}}*/
  291. /*{{{  int in_get()*/
  292. int in_get()    /* get an event from the input buffer */
  293.  
  294. {
  295.         register int event;     /* event to return */
  296.  
  297.         event = in_buf[in_next++];
  298.         in_next &= (IBUFSIZE - 1);
  299.         return(event);
  300. }
  301. /*}}}*/
  302. /*{{{  stuff to set up the keyboard*/
  303.  
  304. /* This is for setting up the keyboard...
  305.   *fx 4,2 sets cursor keys as fn keys
  306.   *fx 220,0 makes ^@ the escape key (change to no interrupt when working)
  307.   *fx 221 to *fx 228 control action of blocks of 16 codes above &80
  308.   *fx 238 sets the base of the numeric keypad
  309.   *fx 254 sets action of control on num keys
  310. */
  311.   
  312.  
  313. static unsigned char armswis[]=
  314.     {4, 221,  222  ,223,  224,  225,  226,  227,  228, 229, 238, 254 };
  315. static unsigned char armvals[]=
  316.     {2, 0xc0, 0xd0, 0xe0, 0xf0, 0x80, 0x90, 0xa0, 0xb0, 1, 0xc0, 0};
  317.  
  318. #define no_fxs (sizeof(armswis))
  319.  
  320. static armstore[no_fxs];
  321. /*}}}*/
  322. /*{{{  PASCAL NEAR ttopen()*/
  323. PASCAL NEAR ttopen()
  324. /*
  325.  * This function is called once to set up the terminal device streams.
  326.  */
  327.  
  328. {       _kernel_swi_regs regs;
  329.         int i;
  330.     
  331.  
  332.         /* on all screens we are not sure of the initial position
  333.            of the cursor                                        */
  334.         ttrow = 999;
  335.         ttcol = 999;
  336.    
  337.         for (i=0; i<no_fxs; ++i)
  338.         {  regs.r[0]=armswis[i];
  339.            regs.r[1]=armvals[i];
  340.            regs.r[2]=0;
  341.            _kernel_swi(6, ®s, ®s);
  342.            armstore[i]=regs.r[1];
  343.         }
  344.  
  345.  
  346.  
  347. }
  348. /*}}}*/
  349. /*{{{  maxlines(lines)*/
  350. maxlines(lines)         /* set number of vertical rows for mouse */
  351.  
  352. int lines;      /* # of vertical lines */
  353.  
  354. {
  355.  
  356. }
  357. /*}}}*/
  358. /*{{{  PASCAL NEAR ttclose()*/
  359. PASCAL NEAR ttclose()
  360.  
  361. /*
  362.  * This function gets called just before we go back home to the command
  363.  * interpreter. On VMS it puts the terminal back in a reasonable state.
  364.  * Another no-operation on CPM.
  365.  */
  366.  
  367. {       _kernel_swi_regs regs;
  368.         int i;
  369.  
  370.         for (i=0; i<no_fxs; ++i)
  371.         {  regs.r[0]=armswis[i];
  372.            regs.r[1]=armstore[i];
  373.            regs.r[2]=0;
  374.            _kernel_swi(6, ®s, ®s);
  375.         }
  376. }
  377. /*}}}*/
  378. /*{{{  PASCAL NEAR ttputc(c)*/
  379. PASCAL NEAR ttputc(c)
  380.  
  381. /*
  382.  * Write a character to the display. On VMS, terminal output is buffered, and
  383.  * we just put the characters in the big array, after checking for overflow.
  384.  * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
  385.  * MS-DOS (use the very very raw console output routine).
  386.  */
  387.  
  388. {
  389.    _kernel_oswrch(c);
  390. }
  391. /*}}}*/
  392. /*{{{  PASCAL NEAR ttflush()*/
  393. PASCAL NEAR ttflush()
  394. /*
  395.  * Flush terminal buffer. Does real work where the terminal output is buffered
  396.  * up. A no-operation on systems where byte at a time terminal I/O is done.
  397.  */
  398. {
  399. }
  400. /*}}}*/
  401. /*{{{  int doschar()*/
  402. int doschar()   /* call the dos to get a char */
  403.  
  404. {  int mask=SPEC; /* only used if a fn key */
  405.    int num;
  406.  
  407.    if ((num=_kernel_osrdch()) < 0x80 ) return(num);
  408.  
  409. /* its a control key - have a look at shift/ctrl and set flags */
  410.  
  411.    num -= 0x80; 
  412.  
  413.    /*{{{  register shift and control bits*/
  414.    if (num & 0x10) num -= 0x10, mask|=SHFT;
  415.    if (num & 0x20) num -= 0x20, mask|=CTRL;
  416.    /*}}}*/
  417.  
  418. /* this seems the way to do it ??? */
  419.  
  420.    in_put(mask>>8);
  421.    
  422.    /*{{{  map keypad 2,4,6,8 to cursor keys*/
  423.    switch (num)
  424.    {  case 0x42 : in_put('E'); return(0);   /* keypad 2 = down */
  425.       case 0x44 : in_put('C'); return(0);   /* keypad 4 = left */
  426.       case 0x46 : in_put('D'); return(0);   /* keypad 6 = right */
  427.       case 0x48 : in_put('F'); return(0);   /* keypad 4 = up */
  428.    }
  429.    /*}}}*/
  430.  
  431.    /*{{{  map other keys to useful FN names*/
  432.    if (num < 10) in_put(num+'0');              /* fn keys are FN0 to FN9 */
  433.    else if (num < 16) in_put(num-10+'A'); /* cursor keys are FNA to FNF */
  434.    else in_put(num - 0x40 + 'G');          /* num keypad is FNG to ... */
  435.    /*}}}*/
  436.    
  437.    return(0); /* tell it that a special code is waiting in the buffer */
  438. }
  439. /*}}}*/
  440. /*{{{  PASCAL NEAR ttgetc()*/
  441. PASCAL NEAR ttgetc()
  442.  
  443. /*
  444.  * Read a character from the terminal, performing no editing and doing no echo
  445.  * at all. Also mouse events are forced into the input stream here.
  446.  */
  447.  
  448. {
  449.         register int c;         /* character read */
  450.  
  451. ttc:    /* return any keystrokes waiting in the
  452.            type ahead buffer */
  453.         if (in_check())
  454.                 return(in_get());
  455.  
  456.         if (typahead())
  457.                 return(doschar());
  458.  
  459.         /* with no mouse, this is a simple get char routine */
  460.         if (mexist == FALSE || mouseflag == FALSE)
  461.                 return(doschar());
  462.  
  463. #if     MOUSE
  464.         /* turn the mouse cursor on */
  465.         rg.x.ax = 1;    /* Show Cursor */
  466.         int86(0x33, &rg, &rg);
  467.  
  468.         /* loop waiting for something to happen */
  469.         while (TRUE) {
  470.                 if (typahead())
  471.                         break;
  472.                 if (checkmouse())
  473.                         break;
  474.         }
  475.  
  476.         /* turn the mouse cursor back off */
  477.         rg.x.ax = 2;    /* Hide Cursor */
  478.         int86(0x33, &rg, &rg);
  479.  
  480.         goto ttc;
  481. #endif
  482. }
  483. /*}}}*/
  484.  
  485. /*{{{  scinit()*/
  486. scinit(mode)
  487. int mode;                   /* -1 means current mode */
  488. {  static int dtype=-1;     /* current mode */
  489.    if (mode==dtype)
  490.      return(FALSE);
  491.  
  492.    _kernel_oswrch(22); _kernel_oswrch(mode);
  493.  
  494.    sprintf(sres, "%d", dtype=mode);  /* update $sres env var */
  495.    return(TRUE);  
  496. }     
  497.    
  498. /*}}}*/
  499.  
  500. #if     MOUSE
  501. /*{{{  checkmouse()*/
  502. checkmouse()
  503.  
  504. {
  505.         register int k;         /* current bit/button of mouse */
  506.         register int event;     /* encoded mouse event */
  507.         int newbut;             /* new state of the mouse buttons */
  508.         int mousecol;           /* current mouse column */
  509.         int mouserow;           /* current mouse row */
  510.         int sstate;             /* current shift key status */
  511.  
  512.         /* check to see if any mouse buttons are different */
  513.         rg.x.ax = 3;    /* Get button status and mouse position */
  514.         int86(0x33, &rg, &rg);
  515.         newbut   = rg.x.bx;
  516.         mousecol = rg.x.cx >> 3;
  517.         mouserow = rg.x.dx >> 3;
  518.  
  519.         /* get the shift key status as well */
  520.         sstate = 0;
  521.         rg.h.ah = 2;    /* return current shift status */
  522.         int86(0x16, &rg, &rg);
  523.         sstate = rg.h.al;
  524.  
  525.         for (k=1; k != (1 << nbuttons); k = k<<1) {
  526.                 /* For each button on the mouse */
  527.                 if ((oldbut&k) != (newbut&k)) {
  528.                         /* This button changed, generate an event */
  529.                         in_put(0);
  530.                         in_put(MOUS >> 8);
  531.                         in_put(mousecol);
  532.                         in_put(mouserow);
  533.                         event = ((newbut&k) ? 0 : 1);   /* up or down? */
  534.                         if (k == 2)                     /* center button? */
  535.                                 event += 4;
  536.                         if (k == 4)                     /* right button? */
  537.                                 event += 2;
  538.                         if (sstate & 3)                 /* shifted */
  539.                                 event += 'A';
  540.                         else if (sstate & 4)            /* controled? */
  541.                                 event += 1;
  542.                         else
  543.                                 event += 'a';           /* plain */
  544.                         in_put(event);
  545.                         oldbut = newbut;
  546.                         return(TRUE);
  547.                 }
  548.         }
  549.         return(FALSE);
  550. }
  551. /*}}}*/
  552. #endif
  553.  
  554. #if     TYPEAH
  555. /*{{{  PASCAL NEAR typahead()*/
  556. PASCAL NEAR typahead()
  557. /* typahead:    Check to see if any characters are already in the
  558.                 keyboard buffer
  559.    osbyte 152 returns carry set for an empty buffer
  560. */
  561.  
  562. {
  563.                 return(!(_kernel_osbyte(152,0,0) >> 16));
  564. }
  565. /*}}}*/
  566. #endif
  567.  
  568. /*{{{  PASCAL NEAR spawncli(f, n)*/
  569. PASCAL NEAR spawncli(f, n)
  570. /*
  571.  * Create a subjob with a copy of the command intrepreter in it. When the
  572.  * command interpreter exits, mark the screen as garbage so that you do a full
  573.  * repaint. Bound to "^X C".
  574.  */
  575.  
  576. {
  577.         /* don't allow this command if restricted */
  578.         if (restflag)
  579.                 return(resterr());
  580.  
  581.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  582.         TTflush();
  583.         TTkclose();
  584.         shellprog("");
  585.         TTkopen();
  586.         sgarbf = TRUE;
  587.         return(TRUE);
  588. }
  589. /*}}}*/
  590. /*{{{  PASCAL NEAR spawn(f, n)*/
  591. PASCAL NEAR spawn(f, n)
  592. /*
  593.  * Run a one-liner in a subjob. When the command returns, wait for a single
  594.  * character to be typed, then mark the screen as garbage so a full repaint is
  595.  * done. Bound to "C-X !".
  596.  */
  597. {
  598.         register int s;
  599.         char line[NLINE];
  600.  
  601.         /* don't allow this command if restricted */
  602.         if (restflag)
  603.                 return(resterr());
  604.  
  605.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  606.                 return(s);
  607.         movecursor(term.t_nrow - 1, 0);
  608.         TTkclose();
  609.         shellprog(line);
  610.         TTkopen();
  611.         /* if we are interactive, pause here */
  612.         if (clexec == FALSE) {
  613.                 mlputs(TEXT6);
  614. /*                     "\r\n\n[End]" */
  615.                 tgetc();
  616.         }
  617.         sgarbf = TRUE;
  618.         return (TRUE);
  619. }
  620. /*}}}*/
  621. /*{{{  PASCAL NEAR execprg(f, n)*/
  622. PASCAL NEAR execprg(f, n)
  623. /*
  624.  * Run an external program with arguments. When it returns, wait for a single
  625.  * character to be typed, then mark the screen as garbage so a full repaint is
  626.  * done. Bound to "C-X $".
  627.  */
  628.  
  629. {
  630.         register int s;
  631.         char line[NLINE];
  632.  
  633.         /* don't allow this command if restricted */
  634.         if (restflag)
  635.                 return(resterr());
  636.  
  637.         if ((s=mlreply("$", line, NLINE)) != TRUE)
  638.                 return(s);
  639.         movecursor(term.t_nrow - 1, 0);
  640.         TTkclose();
  641.         execprog(line);
  642.         TTkopen();
  643.         /* if we are interactive, pause here */
  644.         if (clexec == FALSE) {
  645.                 mlputs(TEXT6);
  646. /*                     "\r\n\n[End]" */
  647.                 tgetc();
  648.         }
  649.         sgarbf = TRUE;
  650.         return (TRUE);
  651. }
  652. /*}}}*/
  653. /*{{{  PASCAL NEAR pipecmd(f, n)*/
  654. PASCAL NEAR pipecmd(f, n)
  655. /*
  656.  * Pipe a one line command into a window
  657.  * Bound to ^X @
  658.  */
  659. {
  660.  
  661. }
  662. /*}}}*/
  663. /*{{{  PASCAL NEAR filter(f, n)*/
  664. PASCAL NEAR filter(f, n)
  665.  
  666. /*
  667.  * filter a buffer through an external DOS program
  668.  * Bound to ^X #
  669.  */
  670. {
  671.   
  672. }
  673. /*}}}*/
  674.  
  675. /*{{{  PASCAL NEAR shellprog(cmd)*/
  676. PASCAL NEAR shellprog(cmd)
  677.  
  678. /*      SHELLPROG: Execute a command in a subshell              */
  679.  
  680. char *cmd;      /*  Incoming command line to execute  */
  681.  
  682. {
  683.  
  684. }
  685. /*}}}*/
  686. /*{{{  PASCAL NEAR execprog(cmd)*/
  687. PASCAL NEAR execprog(cmd)
  688.  
  689. /*      EXECPROG:       A function to execute a named program
  690.                         with arguments
  691. */
  692.  
  693. #if     LATTICE | AZTEC | MWC
  694. #define CFLAG   1
  695. #endif
  696.  
  697. char *cmd;      /*  Incoming command line to execute  */
  698.  
  699. {
  700.  
  701. }
  702. /*}}}*/
  703.  
  704. /*{{{  char *PASCAL NEAR timeset()*/
  705. char *PASCAL NEAR timeset()
  706. /* return a system dependant string with the current time */
  707.  
  708. {  static char buffer[40];
  709.    time_t now;
  710.    time(&now);
  711.    if (strftime(buffer, 40, "%c", localtime(&now)))
  712.      return (buffer);
  713.    return (NULL);
  714. }
  715. /*}}}*/
  716.  
  717.  
  718. /*      FILE Directory routines         */
  719.  
  720. #if     COMPLET & (TURBO)
  721.  
  722. char path[NFILEN];      /* path of file to find */
  723. char rbuf[NFILEN];      /* return file buffer */
  724.  
  725. /*{{{  char *PASCAL NEAR getffile(fspec)*/
  726. char *PASCAL NEAR getffile(fspec)
  727. /*      do a wild card directory search (for file name completion) */
  728.  
  729. char *fspec;    /* pattern to match */
  730.  
  731. {
  732.         register int index;             /* index into various strings */
  733.         register int point;             /* index into other strings */
  734.         register int extflag;           /* does the file have an extention? */
  735.         char fname[NFILEN];             /* file/path for DOS call */
  736.  
  737.         /* first parse the file path off the file spec */
  738.         strcpy(path, fspec);
  739.         index = strlen(path) - 1;
  740.         while (index >= 0 && (path[index] != '/' &&
  741.                                 path[index] != '\\' && path[index] != ':'))
  742.                 --index;
  743.         path[index+1] = 0;
  744.  
  745.         /* check for an extension */
  746.         point = strlen(fspec) - 1;
  747.         extflag = FALSE;
  748.         while (point >= 0) {
  749.                 if (fspec[point] == '.') {
  750.                         extflag = TRUE;
  751.                         break;
  752.                 }
  753.                 point--;
  754.         }
  755.  
  756.         /* construct the composite wild card spec */
  757.         strcpy(fname, path);
  758.         strcat(fname, &fspec[index+1]);
  759.         strcat(fname, "*");
  760.         if (extflag == FALSE)
  761.                 strcat(fname, ".*");
  762.  
  763.         /* and call for the first file */
  764.         if (findfirst(fname, &fileblock, 0) == -1)
  765.                 return(NULL);
  766.  
  767.         /* return the first file name! */
  768.         strcpy(rbuf, path);
  769.         strcat(rbuf, fileblock.ff_name);
  770.         mklower(rbuf);
  771.         return(rbuf);
  772. }
  773. /*}}}*/
  774. /*{{{  char *PASCAL NEAR getnfile()*/
  775. char *PASCAL NEAR getnfile()
  776.  
  777. {
  778.         register int index;             /* index into various strings */
  779.         register int point;             /* index into other strings */
  780.         register int extflag;           /* does the file have an extention? */
  781.         char fname[NFILEN];             /* file/path for DOS call */
  782.  
  783.         /* and call for the first file */
  784.         if (findnext(&fileblock) == -1)
  785.                 return(NULL);
  786.  
  787.         /* return the first file name! */
  788.         strcpy(rbuf, path);
  789.         strcat(rbuf, fileblock.ff_name);
  790.         mklower(rbuf);
  791.         return(rbuf);
  792. }
  793. /*}}}*/
  794.  
  795. #else
  796.  
  797. /*{{{  char *PASCAL NEAR getffile(fspec)*/
  798. char *PASCAL NEAR getffile(fspec)
  799.  
  800. char *fspec;    /* file to match */
  801.  
  802. {
  803.         return(NULL);
  804. }
  805. /*}}}*/
  806. /*{{{  char *PASCAL NEAR getnfile()*/
  807. char *PASCAL NEAR getnfile()
  808.  
  809. {
  810.         return(NULL);
  811. }
  812. /*}}}*/
  813.  
  814. #endif
  815. /*}}}*/
  816.